iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
1

昨天介紹的陣列有一個致命缺點,就是他的長度是固定的不能改變

而今天要來介紹一個比陣列更有彈性的組合型別──切片。

但也因為比較彈性,所以要學的部份就比較多

切片 Slice

切片原理

切片是由三個部分組成而成

  1. 陣列
  2. 容量 capacity
  3. 長度 length

直接看例子:

package main
import "fmt"
func main(){
    role  := [...]string{"小櫻", "知世", "小可", "小狼", "苺鈴"}
    slice := role[0:3]          // [0] [1] [2]
    fmt.Println(slice)
    fmt.Println(role)           // 陣列
    fmt.Println(len(slice))     // 長度
    fmt.Println(cap(slice))     // 容量
}

執行結果:
[小櫻 知世 小可]
[小櫻 知世 小可 小狼 苺鈴]
3
5

其中重點就在 role[0:3] 這到底是什麼意思呢?這個就是只我在 0 的左邊切一刀 3 的左邊切一刀

[0 "小櫻"][1 "知世"][2 "小可"][3 "小狼"][4 "苺鈴"]

這樣 slice 就會從 role 裡面挑出 0, 1, 2 形成切片

而所謂的容量就是指原本 role 的長度:5個角色,而長度則是指切出來的長度3

利用指向不同的陣列,可以實現容量、長度都可以變動的切片

宣告一個有預設長度、容量的切片

除了直接從陣列切來,也可以用 make 來宣告一個新的切片

其中第一個參數是切片的型態比如 []int []string

第二個參數填入長度 len ,第三個參數填入容量 cap

其中長度不可超過容量,容量是底層陣列的長度,一般情況長度是可以輕易改變的,若要改變容量則必需重新更換底層陣列

package main
import "fmt"
func main(){
    slice := make([]string, 3, 5)
    slice[0] = "小櫻"
    slice[1] = "知世"
    slice[2] = "小可"
    fmt.Println(slice)
    fmt.Println(len(slice))     // 長度
    fmt.Println(cap(slice))     // 容量
}

執行結果:

[小櫻 知世 小可]
3
5

宣告一個長度與容量相同的切片

在宣告時可以省略第三個參數,如果僅指定第二個參數,那麼就代表宣告一個長度與容量相同的切片

package main
import "fmt"
func main(){
    slice := make([]string, 5)
    slice[0] = "小櫻"
    slice[1] = "知世"
    slice[2] = "小可"
    fmt.Println(slice)
    fmt.Println(len(slice))     // 長度
    fmt.Println(cap(slice))     // 容量
}

執行結果:

[小櫻 知世 小可 ]
5
5

快速宣告一個切片

除了用 make 宣告還可以用向陣列一樣宣告的方法

package main
import "fmt"
func main(){
    slice := []string{"小櫻", "知世", "小可"}
    fmt.Println(slice)
    fmt.Println(len(slice))     // 長度
    fmt.Println(cap(slice))     // 容量
}

執行結果:

[小櫻 知世 小可]
3
3

要注意的是,宣告陣列時是用 [...]string{} 而使用切片時是用 []string{}

append()

宣告切片時,如果不確定要用多少容量,可以先宣告一個空切片,並且使用append() 來插入新的值。在使用 append() 時不需要考慮切片的容量,golang會自己解決,這就是切片好用的地方

package main
import "fmt"
func main(){
    slice := []string{}         // 宣告空切片
    slice = append(slice, "小櫻")
    slice = append(slice, "知世")
    slice = append(slice, "小可")

    fmt.Println(slice)
    fmt.Println(len(slice))     // 長度
    fmt.Println(cap(slice))     // 容量(append 時容量不夠會自動增加)
}

走訪

跟陣列一樣 slice 也可以利用 for 進行走訪

package main
import "fmt"
func main(){
    slice := []string{"小櫻", "知世", "小可"}
    for i := 0; i<len(slice); i = i+1{
        fmt.Printf("%d : %s\n", i, slice[i])
    }
}

跟陣列一樣 slice 也可以利用 for + range 進行走訪

package main
import "fmt"
func main(){
    slice := []string{"小櫻", "知世", "小可"}
    for k, v := range slice{
        fmt.Printf("%d : %s\n", k, v)
    }
}

執行結果:
0 : 小櫻
1 : 知世
2 : 小可

如果不使用 value 值則規則與走訪陣列一致,將 value 設成 _ 即可

後記

小櫻真嗨

本文多數圖片來自:
圖源:庫洛魔法使第一季第十二集


上一篇
#7 陣列 Array | Golang魔法使
下一篇
#9 映射 Map ── 雪兔:除非是有魔法的人否則根本辦不到的 | Golang魔法使
系列文
Golang魔法使 ─ 30天從零開始學習Go語言 | 比Python還簡單 | 理科生一定學得會 | 文科生不好說30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言